package com.whpost.service.tools;

import com.github.stuxuhai.jpinyin.PinyinHelper;
import jakarta.servlet.http.HttpServletRequest;
import org.slf4j.LoggerFactory;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.text.DateFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.IsoFields;
import java.time.temporal.TemporalAdjusters;
import java.util.*;

/**
 * @author Yinzhuoyi
 * @Description 工具类
 * @date 2020/5/12 15:44
 */
public class ToolBean {
    /**
     * 主动打印日志信息
     * @param str
     */
    public static void info(String str)
    {
        LoggerFactory.getLogger(ToolBean.class).info(new Date()+" "+str);
    }

    public static Date getToday()
    {
        Date date = new Date();
        return date;
    }

    public static String getTodayStr(String str)
    {
        SimpleDateFormat sdf = new SimpleDateFormat(str);
        Date date = new Date();
        String formattedDate = sdf.format(date);
        return formattedDate;
    }

    //获取当前时间+毫秒
    // 1天 = 86400000毫秒  1秒 = 1000毫秒  1分=60000毫秒  1时=3600000毫秒
    public static Date getNowTimeAddMillisecond(long msecond,String pattern) throws ParseException {
        Date date = new Date();
        long time = date.getTime(); // 得到指定日期的毫秒数
        time+=msecond; // 相加得到新的毫秒数
        return new Date(time);
    }

    //获取当前时间+毫秒
    // 1天 = 86400000毫秒  1秒 = 1000毫秒  1分=60000毫秒  1时=3600000毫秒
    public static String getNowTimeAddMillisecondStr(long msecond,String pattern) throws ParseException {
        Date date = new Date();
        long time = date.getTime(); // 得到指定日期的毫秒数
        time+=msecond; // 相加得到新的毫秒数
        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
        String formattedDate = sdf.format(new Date(time));
        return formattedDate;
    }

    public static String getDateStr(Date date,String str)
    {
        SimpleDateFormat sdf = new SimpleDateFormat(str);
        String formattedDate = sdf.format(date);
        return formattedDate;
    }

    /**
     * 获取随机字符串
     * @param length 字符串长度
     * @return
     */
    public static String getRandomString(int length)
    {
        String base = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789abcdefghjkmnpqrstu";
        Random random = new Random();
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < length; i++) {
            int number = random.nextInt(base.length());
            sb.append(base.charAt(number));
        }
        return sb.toString();
    }

    public static void tc(String lj1,String lj2,String bj,String hclj) throws IOException {
        BufferedImage background = ImageIO.read(new File(bj));
        // 实例化Graphics2D对象
        Graphics2D g2d = background.createGraphics();
        // 读取要合并的图片1
        BufferedImage overlay1 = ImageIO.read(new File(lj1));
        // 读取要合并的图片2
        BufferedImage overlay2 = ImageIO.read(new File(lj2));
        //覆盖合成列1
        g2d.drawImage(overlay1, 665, 789, 296, 295, null);
        g2d.drawImage(overlay1, 665, 1143, 296, 295, null);
        g2d.drawImage(overlay1, 665, 1498, 296, 295, null);
        g2d.drawImage(overlay1, 665, 1852, 296, 295, null);

        //覆盖合成列2
        g2d.drawImage(overlay1, 1375, 789, 296, 295, null);
        g2d.drawImage(overlay1, 1375, 1852, 296, 295, null);

        //覆盖合成列3
        g2d.drawImage(overlay1, 2089, 789, 296, 295, null);
        g2d.drawImage(overlay1, 2089, 1143, 296, 295, null);
        g2d.drawImage(overlay1, 2089, 1498, 296, 295, null);
        g2d.drawImage(overlay1, 2089, 1852, 296, 295, null);

        //中间图片
        g2d.drawImage(overlay2, 1023, 1142, 1000, 651, null);

        // 保存合并后的图片
        ImageIO.write(background, "png", new File(hclj));
    }

    /**
     * null转为空字符串
     * @param str
     * @return
     */
    public static String ntos(String str)
    {
        if (str == null) str = "";
        return str;
    }

    /**
     * 字符串加密
     * @param str
     * @return
     */
    public static String getEncode(String str)
    {
        try {
            return  java.net.URLEncoder.encode(Url.encrypt(String.valueOf(str)),"utf-8");
        } catch (Exception e) {
            info("getEncode("+str+")发生错误！");
            return "";
        }
    }
    /**
     * long加密
     * @param str
     * @return
     */
    public static String getEncode(Long str)
    {
        try {
            return java.net.URLEncoder.encode(Url.encrypt(String.valueOf(str)),"utf-8");
        } catch (Exception e) {
            info("getEncode("+str+")发生错误！");
            return "";
        }
    }

    /**
     * 字符串解密
     * @param str
     * @return
     */
    public static String getDecode(String str)
    {
        try {
            return Url.decrypt(str);
        } catch (Exception e) {
            info("getDecode("+str+")发生错误！");
            return "";
        }
    }

    /**
     * 字符串解密
     * @param str
     * @return
     */
    public static String getDecodeWithNetDecode(String str)
    {
        try {
            return Url.decrypt(java.net.URLDecoder.decode(str,"utf-8"));
        } catch (Exception e) {
            info("getDecode("+str+")发生错误！");
            return "";
        }
    }

    /**
     * 拼接list内容，逗号分隔
     * @param list
     * @return
     */
    public static String getListStr(ArrayList<String> list){

        String result = "";
        if (null!=list){
            result = String.join(",", list);
        }
        return result;
    }

    /**
     *
     *  sql和xss校验
     * @param str
     * @return
     */
    public static boolean sqlAndXssValidate(String str) {
        str = ntos(str);
        str = str.toLowerCase();//统一转为小写
        String badStr = "'|and|exec|execute|insert|select|delete|update|count|drop|*|%|chr|mid|master|truncate|" +
                "char|declare|sitename|net user|xp_cmdshell|;|or|-|+|,|like'|and|exec|execute|insert|create|drop|" +
                "table|from|grant|use|group_concat|column_name|" +
                "information_schema.columns|table_schema|union|where|select|delete|update|order|by|count|*|" +
                "chr|mid|master|truncate|char|declare|or|;|-|--|+|,|like|//|/|%|#|script|iframe|alert|<|>|on|location|document";//过滤掉的sql关键字，可以手动添加
        String[] badStrs = badStr.split("\\|");
        for (int i = 0; i < badStrs.length; i++) {
            if (str.indexOf(badStrs[i]) >= 0) {
                info("参数值：【"+str+"】检测到不合法字符："+badStrs[i]);
                return false;
            }
        }
        return true;
    }


    /**
     * 返回日期+天
     * @param date
     * @param i
     * @return
     */
    public static Date getDayAddDates(Date date,int i){
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(Calendar.DATE, i);
        Date newDate = c.getTime();
        return newDate;
    }

    /**
     * 校验密码是否强壮
     * @param passWord
     * @return
     */
    public static Boolean checkPassWordIsStrong(String passWord) {
        if (passWord == null)
            return false;
        if (passWord.length() < 8 || passWord.length() > 20)
            return false;
        int count = 0;
        if (passWord.matches(".*[A-Z].*"))
            count ++;
        if (passWord.matches(".*[a-z].*"))
            count ++;
        if (passWord.matches(".*[0-9].*"))
            count ++;
        if (passWord.matches(".*\\p{Punct}.*"))
            count ++;
        return count >= 2;
    }
    private static char[] base64EncodeChars = new char[] { 'A', 'B', 'C', 'D',
            'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q',
            'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', 'a', 'b', 'c', 'd',
            'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q',
            'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '0', '1', '2', '3',
            '4', '5', '6', '7', '8', '9', '+', '/', };

    private static byte[] base64DecodeChars = new byte[] { -1, -1, -1, -1, -1,
            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
            -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1,
            -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59,
            60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
            10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1,
            -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37,
            38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1,
            -1, -1 };

    /**
     * 解密登录密码的密文
     * @param str
     * @return
     */
    public static byte[] decode(String str) {
        byte[] data = str.getBytes();
        int len = data.length;
        ByteArrayOutputStream buf = new ByteArrayOutputStream(len);
        int i = 0;
        int b1, b2, b3, b4;

        while (i < len) {
            do {
                b1 = base64DecodeChars[data[i++]];
            } while (i < len && b1 == -1);
            if (b1 == -1) {
                break;
            }

            do {
                b2 = base64DecodeChars[data[i++]];
            } while (i < len && b2 == -1);
            if (b2 == -1) {
                break;
            }
            buf.write((int) ((b1 << 2) | ((b2 & 0x30) >>> 4)));

            do {
                b3 = data[i++];
                if (b3 == 61) {
                    return buf.toByteArray();
                }
                b3 = base64DecodeChars[b3];
            } while (i < len && b3 == -1);
            if (b3 == -1) {
                break;
            }
            buf.write((int) (((b2 & 0x0f) << 4) | ((b3 & 0x3c) >>> 2)));

            do {
                b4 = data[i++];
                if (b4 == 61) {
                    return buf.toByteArray();
                }
                b4 = base64DecodeChars[b4];
            } while (i < len && b4 == -1);
            if (b4 == -1) {
                break;
            }
            buf.write((int) (((b3 & 0x03) << 6) | b4));
        }
        return buf.toByteArray();
    }

    /**
     * MD5加密
     * @param str
     * @return
     */
    public static String getMD5Str(String str) {
        MessageDigest messageDigest = null;

        try {
            messageDigest = MessageDigest.getInstance("MD5");

            messageDigest.reset();

            messageDigest.update(str.getBytes("UTF-8"));
        } catch (NoSuchAlgorithmException e) {
            info("NoSuchAlgorithmException caught!");
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        byte[] byteArray = messageDigest.digest();

        StringBuffer md5StrBuff = new StringBuffer();

        for (int i = 0; i < byteArray.length; i++) {
            if (Integer.toHexString(0xFF & byteArray[i]).length() == 1)
                md5StrBuff.append("0").append(Integer.toHexString(0xFF & byteArray[i]));
            else
                md5StrBuff.append(Integer.toHexString(0xFF & byteArray[i]));
        }

        return md5StrBuff.toString();
    }

    public static String getPy(String str) {
        try {
            String rtn = "";
            rtn = PinyinHelper.getShortPinyin(str);
            return rtn.toUpperCase();
        }
        catch(Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }

    /**
     * 月第一天
     * @return
     */
    public static String getMonthFirstDay(){
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_MONTH,1);
        calendar.add(Calendar.MONTH,0);
        return new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime());
    }

    /**
     * 月最后一天
     * @return
     */
    public static String getMonthLastDay(){
        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        return new SimpleDateFormat("yyyy-MM-dd").format(calendar.getTime());
    }

    /**
     * 校验日期格式
     * @param length
     * @param sDate
     * @param format
     * @return
     */
    public static boolean isLegalDate(int length, String sDate,String format) {
        int legalLen = length;
        if ((sDate == null) || (sDate.length() != legalLen)) {
            return false;
        }
        DateFormat formatter = new SimpleDateFormat(format);
        try {
            Date date = formatter.parse(sDate);
            return sDate.equals(formatter.format(date));
        } catch (Exception e) {
            return false;
        }
    }

    /**
     * 校验日期格式 yyyy-MM-dd HH:mm:ss
     * @param dateStr
     * @return
     */
    public static boolean isValidDateTime(String dateStr) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        sdf.setLenient(false); // 严格解析，防止类似 "2023-02-30" 被解析
        try {
            Date date = sdf.parse(dateStr);
            return true;
        } catch (ParseException e) {
            return false;
        }
    }

    /**
     * 日期+天数 yyyy-MM-dd
     * @param rq
     * @param ts
     * @return
     */
    public static String rqAdd(String rq,long ts,String format) {
        SimpleDateFormat dateFormat = new SimpleDateFormat(format); // 日期格式
        Date date = null; // 指定日期
        try {
            date = dateFormat.parse(rq);
        } catch (ParseException e) {
            throw new RuntimeException(e);
        }
        long time = date.getTime(); // 得到指定日期的毫秒数
        ts = ts*24*60*60*1000; // 要加上的天数转换成毫秒数
        time+=ts; // 相加得到新的毫秒数
        return dateFormat.format(new Date(time));
    }

    public static String getWeekOfYear(String rq) throws ParseException {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); // 日期格式
        Date date = dateFormat.parse(rq); // 指定日期
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return String.valueOf(calendar.get(Calendar.WEEK_OF_YEAR));
    }

    public static int getWeekSl(int year) throws ParseException {
        LocalDate firstDayOfYear = LocalDate.of(year, 1, 1);
        LocalDate firstThursday = firstDayOfYear.with(TemporalAdjusters.nextOrSame(java.time.DayOfWeek.THURSDAY));
        LocalDate firstWeekStart = firstThursday.minusDays(java.time.DayOfWeek.THURSDAY.getValue() - 1);
        LocalDate lastDayOfYear = LocalDate.of(year, 12, 31);
        LocalDate lastThursday = lastDayOfYear.with(TemporalAdjusters.previousOrSame(java.time.DayOfWeek.THURSDAY));
        LocalDate lastWeekStart = lastThursday.minusDays(java.time.DayOfWeek.THURSDAY.getValue() - 7);

        return (int) (lastWeekStart.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR) - firstWeekStart.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR) + 1);
    }

    public static String getWeek()
    {
        LocalDate today = LocalDate.now();
        int weekOfYear = today.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR);
        return String.valueOf(weekOfYear);
    }

    public static String getYear(){
        LocalDate currentDate = LocalDate.now();  // 获取当前日期
        int year = currentDate.getYear();  // 获取年份
        return String.valueOf(year);
    }

    public static String getYear(int sl){
        LocalDate currentDate = LocalDate.now();  // 获取当前日期
        int year = currentDate.getYear();  // 获取年份
        return String.valueOf(year-sl);
    }

    public static String getNextYear(){
        LocalDate currentDate = LocalDate.now();  // 获取当前日期
        int year = currentDate.getYear();  // 获取年份
        return String.valueOf(year+1);
    }

    public static boolean isValidIP(String ipAddress) {
        String ipPattern = "^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$";
        return ipAddress.matches(ipPattern);
    }

    public static String getIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
        }
        if (ip.contains(",")) {
            return ip.split(",")[0];
        } else {
            return ip;
        }
    }

    public static Double Rounding(Double number){
        BigDecimal bd = new BigDecimal(Double.toString(number));
        // 保留两位小数，使用四舍五入模式
        bd = bd.setScale(2, RoundingMode.HALF_UP);
        return bd.doubleValue();
    }

    public static String divideAndFormat(double dividend, double divisor, int scale) {
        // 避免除数为零
        if (divisor == 0) {
            return "0%";
        }
        // 使用 BigDecimal 进行精确计算
        BigDecimal bdDividend = new BigDecimal(Double.toString(dividend));
        BigDecimal bdDivisor = new BigDecimal(Double.toString(divisor));
        // 进行除法运算并四舍五入
        BigDecimal result = bdDividend.divide(bdDivisor, scale + 2, RoundingMode.HALF_UP);
        result = result.multiply(new BigDecimal("100")).setScale(scale, RoundingMode.HALF_UP);
        // 创建百分比格式化对象
        NumberFormat percentFormat = NumberFormat.getPercentInstance();
        percentFormat.setMinimumFractionDigits(scale);
        // 将结果格式化为百分比
        return percentFormat.format(result.movePointLeft(2).doubleValue());
    }

    //首字母变大写
    public static String capitalizeFirstLetter(String str) {
        if (str == null || str.length() == 0) {
            return str;
        }
        return Character.toUpperCase(str.charAt(0)) + str.substring(1);
    }

    /**
     *
     * @param args
     */

    public static void main(String[] args) throws ParseException {
        //System.out.println("now: " + getDateStr(new Date(),"yyyyMMddHHmmss"));

        double dividend =  953626.24;
        double divisor =  29507567.44;
        int scale = 1;
        String percentage = divideAndFormat(dividend, divisor, scale);
        System.out.println("结果: " + percentage);
    }
}
